/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var dal = require("./dal.js");
model = module.exports;

var OAuthAccessTokenTable = "oauth2accesstoken";
var OAuthRefreshTokenTable = "oauth2refreshtoken";

var OAuthAuthCodeTable = "oauth2authcode";

var OAuthClientTable = "oauth2client";
var OAuthUserTable = "userid_map";

//
// oauth2-server callbacks
//
model.getAccessToken = function (bearerToken, callback) {
    console.log("in getAccessToken (bearerToken: " + bearerToken + ")");

    dal.doGet(OAuthAccessTokenTable,
        {"accessToken": {"S": bearerToken}}, true, function(err, data) {
            if (data && data.expires) {
                data.expires = new Date(data.expires * 1000);
            }
            callback(err, data);
        });
};

model.getClient = function (clientId, clientSecret, callback) {
    console.log("in getClient (clientId: " + clientId + ", clientSecret: " + clientSecret + ")");
    dal.doGet(OAuthClientTable, { clientId: { S: clientId }}, true,
        function(err, data) {
            if (err || !data) return callback(err, data);

            if (clientSecret !== null && data.clientSecret !== clientSecret) {
                return callback();
            }

            callback(null, data);
        });
};

// This will very much depend on your setup, I wouldn"t advise doing anything exactly like this but
// it gives an example of how to use the method to restrict certain grant types
var authorizedClientIds = ["abc1", "def2"];
model.grantTypeAllowed = function (clientId, grantType, callback) {
    console.log("in grantTypeAllowed (clientId: " + clientId + ", grantType: " + grantType + ")");

    if (grantType === "password") {
        return callback(false, authorizedClientIds.indexOf(clientId) >= 0);
    }

    callback(false, true);
};

model.saveAccessToken = function (accessToken, clientId, expires, user, callback) {
    console.log("in saveAccessToken (accessToken: " + accessToken + ", clientId: " + clientId + ", userId: " + user.id + ", expires: " + expires + ")");

    var token = {
        accessToken: accessToken,
        clientId: clientId,
        userId: user.id
    };

    if (expires) token.expires = parseInt(expires / 1000, 10);
    console.log("saving", token);

    dal.doSet(token, OAuthAccessTokenTable, { accessToken: { S: accessToken }}, callback);
};

model.saveRefreshToken = function (refreshToken, clientId, expires, user, callback) {
    console.log("in saveRefreshToken (refreshToken: " + refreshToken + ", clientId: " + clientId + ", userId: " + user.id + ", expires: " + expires + ")");

    var token = {
        refreshToken: refreshToken,
        clientId: clientId,
        userId: user.id
    };

    if (expires) token.expires = parseInt(expires / 1000, 10);
    console.log("saving", token);

    dal.doSet(token, OAuthRefreshTokenTable, { refreshToken: { S: refreshToken }}, callback);
};

model.getRefreshToken = function (bearerToken, callback) {
    console.log("in getRefreshToken (bearerToken: " + bearerToken + ")");

    dal.doGet(OAuthRefreshTokenTable, { refreshToken: { S: bearerToken }}, true, function(err, data) {
        if (data && data.expires) {
            data.expires = new Date(data.expires * 1000);
        }
        callback(err, data);
    });
};

model.revokeRefreshToken = function(bearerToken, callback) {
    console.log("in revokeRefreshToken (bearerToken: " + bearerToken + ")");

    dal.doDelete(OAuthRefreshTokenTable, { refreshToken: { S: bearerToken }}, callback);
};

model.getAuthCode = function (bearerCode, callback) {
    console.log("in getAuthCode (bearerCode: " + bearerCode + ")");

    dal.doGet(OAuthAuthCodeTable, { authCode: { S: bearerCode }}, true, function(err, data) {
        if (data && data.expires) {
            data.expires = new Date(data.expires * 1000);
        }
        callback(err, data);
    });
};

model.saveAuthCode = function (authCode, clientId, expires, user, callback) {
    console.log("in saveAuthCode (authCode: " + authCode + ", clientId: " + clientId + ", userId: " + user.id + ", expires: " + expires + ")");

    var code = {
        authCode: authCode,
        clientId: clientId,
        userId: user.id
    };

    if (expires) code.expires = parseInt(expires / 1000, 10);
    console.log("saving", code);

    dal.doSet(code, OAuthAuthCodeTable, { authCode: { S: authCode }}, callback);
};


/*
 * Required to support password grant type
 */
model.getUser = function (username, password, callback) {
    console.log("in getUser (username: " + username + ", password: " + password + ")");

    dal.doGet(OAuthUserTable, { id: { S: "email:" + username}}, true, function(err, data) {
        if (err) return callback(err);
        callback(null, { id: data.userId });
    });
};
